package com.ytlz.dmcs.model.system.view;

import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

import javax.servlet.http.HttpServletRequest;

import org.bson.Document;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.ytlz.dmcs.model.system.dao.SysObjectDao;
import com.ytlz.dmcs.model.system.dao.UserDao;
import com.ytlz.dmcs.model.system.entity.SysField;
import com.ytlz.dmcs.model.system.entity.SysObject;
import com.ytlz.dmcs.model.system.entity.SysUser;

public class BaseView {
	@Autowired
	private MongoTemplate mongoTemplate;

	@Autowired
	private UserDao userDao;
	
	public MongoTemplate getMongoTemplate() {
		return mongoTemplate;
	}

	public void setMongoTemplate(MongoTemplate mongoTemplate) {
		this.mongoTemplate = mongoTemplate;
	}
	
	@Autowired
	private SysObjectDao sysObjectDao;
	
	
		
	public SysObjectDao getSysObjectDao() {
		return sysObjectDao;
	}

	public void setSysObjectDao(SysObjectDao sysObjectDao) {
		this.sysObjectDao = sysObjectDao;
	}

	protected SysUser getCurrentUser() {
		UserDetails userDetails = (UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
		
		SysUser userObj = userDao.findByUsername(userDetails.getUsername());		
		return userObj;
	}
	
	@RequestMapping("getData")
	@ResponseBody
 	public Map<String, Object> getData(HttpServletRequest request,@RequestParam(value="type" ,required=true) String type) {
		Map<String,Object> result = new HashMap<String, Object>();  
		Query query = new Query();
		Enumeration<String> names = request.getParameterNames();
		Criteria c = null;		
		while (names.hasMoreElements()) {
			String name = names.nextElement();
			Pattern pattern = Pattern.compile("^.*"+ request.getParameter(name) +".*$", Pattern.CASE_INSENSITIVE);
			if(name.startsWith("query.")) {
				String key = name.replace("query.", "");
				if(c==null) {
					c=Criteria.where(key).regex(pattern);
				}else {
					c.and(key).regex(pattern);
				}
			}
		}
		if(c!=null) {			
			query.addCriteria(c);
		}
		
		if(request.getParameter("sort")!=null && request.getParameter("order")!=null) {
			String sort=request.getParameter("sort");
			String order=request.getParameter("order");
			Direction direction= order.toLowerCase().equals("asc")?Direction.ASC:Direction.DESC;
			query.with(Sort.by(direction, sort));
		}
		
		if(request.getParameter("page")!=null && request.getParameter("rows")!=null) {			
			String page = request.getParameter("page");
			String rows = request.getParameter("rows");
			int pageNumber  = Integer.parseInt(page)-1;
			int limit = Integer.parseInt(rows);		
			query.with(PageRequest.of(pageNumber, limit));
		}

		
		long count = this.getMongoTemplate().count(query, type);		
		List<Document> rows = this.getMongoTemplate().find(query, Document.class, type);
		List<Document> rowsList = new ArrayList<Document>();
		for (Document document : rows) {
			ObjectId id = document.getObjectId("_id");
			document.append("id", id.toString());
			if(document.get("parent_id")!=null && document.get("parent_id").toString().trim().length()>0) {
				Document parentObj = this.getMongoTemplate().findById(new ObjectId(document.get("parent_id").toString()), Document.class, type);
				if(parentObj!=null) {
					document.append("parent_name", parentObj.getString("text"));
				}
			}
			
			rowsList.add(document);
		}
		result.put("total", count);
		result.put("rows", rowsList);			
		return result;
	}
	
	protected List<SysField> getScopeAttributes(String type,String scopeName) {
		List<SysField> result = new ArrayList<SysField>();
		SysObject obj = this.getSysObjectDao().findByName(type);
		if(obj!=null) {
			List<SysField> fs = obj.getFields();
			for (SysField sysField : fs) {
				if(!sysField.getName().toLowerCase().endsWith("date")) {
					result.add(sysField);
				}
			}
		}		
		return result;
	}
	
	protected List<SysField> filterQueryAttributes(List<SysField> fields){
		List<SysField> result = new ArrayList<SysField>();
		for (SysField sysField : fields) {
			if(!sysField.getName().endsWith("date")) {
				result.add(sysField);
			}
		}
		return result;
	}
	
		
	protected String type(String type) {
		Query query = new Query();
		query.addCriteria(Criteria.where("code").is(type));
		Document obj = this.getMongoTemplate().findOne(query, Document.class,"sys_object");
		if(obj!=null) {
			return obj.getString("text");
		}else {
			return type;
		}
	}
	
	protected List<Map<String, Object>> getAllMenusCustom() {
		Query query = new Query();
		Criteria c1 = Criteria.where("parent_id").exists(false);
		Criteria c2 = Criteria.where("parent_id").is("");
		Criteria orC = new Criteria();
		orC.orOperator(c1,c2);
		query.addCriteria(orC);
		List<Document> rootObjList =  this.getMongoTemplate().find(query, Document.class,"sys_menu");
		List<Map<String, Object>> result = new ArrayList<Map<String,Object>>();		
		for (Document document : rootObjList) {
			Map<String, Object> menu= new HashMap<String,Object>();
			menu.put("id", document.getObjectId("_id").toString());
			menu.put("text", document.getString("text"));
			
			Query queryForMenu = new Query();
			queryForMenu.addCriteria(Criteria.where("parent_id").is(document.getObjectId("_id").toString()));
			List<Document> childList = this.getMongoTemplate().find(queryForMenu, Document.class,"sys_menu");
			if(childList!=null && childList.size()>0) {
				List<Map<String, Object>> children =  new ArrayList<Map<String,Object>>();
				for (Document childObj : childList) {
					Map<String, Object> child= new HashMap<String,Object>();
					child.put("id", childObj.getObjectId("_id").toString());
					child.put("text", childObj.getString("text"));
					
					Map<String, Object> attributes = new HashMap<String,Object>();
					attributes.put("url", childObj.get("url")==null?"#":childObj.getString("url"));
					child.put("attributes",attributes);
					children.add(child);
				}
				menu.put("children", children);
			}else {
				Map<String, Object> attributes = new HashMap<String,Object>();
				String url = document.getString("url")==null?"#":document.getString("url");
				attributes.put("url", url);
				menu.put("attributes",attributes);
			}
			result.add(menu);
		}		
		return result;
	}
	
	protected List<Map<String, Object>> getAllMenus(String menutype) {
		Query query = new Query();
		Criteria c1 = Criteria.where("parent_id").exists(false);
		Criteria c2 = Criteria.where("parent_id").is("");
		Criteria orC = new Criteria();
		orC.orOperator(c1,c2);		
		switch (menutype) {
		case "system":
			Criteria crS = Criteria.where("type").in("system","public");
			crS.andOperator(orC);
			query.addCriteria(crS);
			break;
		case "custom":
			Criteria crC = Criteria.where("type").in("custom","public");
			crC.andOperator(orC);
			query.addCriteria(crC);
			break;
		default:			
			query.addCriteria(orC);
			break;
		}		
		List<Document> rootObjList =  this.getMongoTemplate().find(query, Document.class,"sys_menu");
		List<Map<String, Object>> result = new ArrayList<Map<String,Object>>();		
		for (Document document : rootObjList) {
			Map<String, Object> menu= new HashMap<String,Object>();
			menu.put("id", document.getObjectId("_id").toString());
			menu.put("text", document.getString("text"));			
			Query queryForMenu = new Query();
			queryForMenu.addCriteria(Criteria.where("parent_id").is(document.getObjectId("_id").toString()));
			List<Document> childList = this.getMongoTemplate().find(queryForMenu, Document.class,"sys_menu");
			if(childList!=null && childList.size()>0) {
				List<Map<String, Object>> children =  new ArrayList<Map<String,Object>>();
				for (Document childObj : childList) {
					Map<String, Object> child= new HashMap<String,Object>();
					child.put("id", childObj.getObjectId("_id").toString());
					child.put("text", childObj.getString("text"));
					
					Map<String, Object> attributes = new HashMap<String,Object>();
					attributes.put("url", childObj.get("url")==null?"#":childObj.getString("url"));
					child.put("attributes",attributes);
					children.add(child);
				}
				menu.put("children", children);
			}else {
				Map<String, Object> attributes = new HashMap<String,Object>();
				String url = document.getString("url")==null?"#":document.getString("url");
				attributes.put("url", url);
				menu.put("attributes",attributes);
			}
			result.add(menu);
		}		
		return result;
	}


	@RequestMapping("openCreatePage")
	public String openCreatePage(HttpServletRequest request,Model model,@RequestParam(value="type" ,required=true) String type,@RequestParam(value="dialog" ,required=true) String dialog,@RequestParam(value="table" ,required=true) String table) {		
		if(sysObjectDao.findByName(type)!=null) {
			model.addAttribute("createattributes", getScopeAttributes(type,"createattribute"));			
		}else {
			List<SysField> fields = new ArrayList<SysField>();
			
			switch (type) {
			case "sys_user":
				fields.add(new SysField("username", "登录名", "text","system"));
				fields.add(new SysField("displayname", "用户名", "text","system"));
				fields.add(new SysField("mail", "邮箱", "mail","system"));
				fields.add(new SysField("password", "密码", "password","system"));
				break;
			case "sys_role":
				fields.add(new SysField("name", "角色名", "text","system"));
				fields.add(new SysField("desc", "角色描述", "text","system"));
				break;
			}
			model.addAttribute("createattributes", fields);
		}
		String url = request.getContextPath() + request.getServletPath().replace("/openCreatePage", "");
		model.addAttribute("currentPath",url);		
		model.addAttribute("dialogid",dialog);
		model.addAttribute("tableid",table);
		model.addAttribute("currentType", type);
		
		return getOpenCreatePage();
	}
	
	protected String getOpenCreatePage() {
		return "create";
	}
	
	@RequestMapping("delete")
	@ResponseBody
	public Map<String,Object> removeData(@RequestParam(value="type" ,required=true) String type,@RequestParam(value="id" ,required=true) String id){
		Query query = new Query();
		query.addCriteria(Criteria.where("_id").is(new ObjectId(id)));
		this.getMongoTemplate().remove(query, type);		
		Map<String,Object> result = new HashMap<String,Object>();
		result.put("message", 1);
		return result;
	}
	
	
	
	
	protected Query sortSetting(Query query, HttpServletRequest request) {
		if(request.getParameter("sort")!=null && request.getParameter("order")!=null) {
			String sort=request.getParameter("sort");
			String order=request.getParameter("order");
			Direction direction= order.toLowerCase().equals("asc")?Direction.ASC:Direction.DESC;
			query.with(Sort.by(direction, sort));
		}
		return query;
	}
	
	
	protected Query pagesSetting(Query query, HttpServletRequest request) {
		if(request.getParameter("page")!=null && request.getParameter("rows")!=null) {			
			String page = request.getParameter("page");
			String rows = request.getParameter("rows");
			int pageNumber  = Integer.parseInt(page)-1;
			int limit = Integer.parseInt(rows);		
			
			Pageable pageable = PageRequest.of(pageNumber, limit);
			query.with(pageable);
		}
		return query;
	}
	
	protected Criteria queryParameters(Criteria c, HttpServletRequest request) {
		Enumeration<String> names = request.getParameterNames();
		while (names.hasMoreElements()) {
			String name = names.nextElement();
			Pattern pattern = Pattern.compile("^.*"+ request.getParameter(name) +".*$", Pattern.CASE_INSENSITIVE);
			if(name.startsWith("query.")) {
				String key = name.replace("query.", "");
				if(c==null) {
					c=Criteria.where(key).regex(pattern);
				}else {
					c.and(key).regex(pattern);
				}
			}
		}	
		return c;
	}
}
